package com.mzwise.tunnel.service;

import cn.hutool.json.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.FileItem;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.mzwise.tunnel.service.Configs;
import com.mzwise.tunnel.utils.DateUtils;

import javax.sound.midi.Patch;
import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 支付宝支付相关工具
 */
public class AliPayService {

    private AlipayClient alipayClient;

    public AliPayService(Configs configs) {
        if (configs.getAlipayClient() != null) {
            try {
                this.alipayClient = configs.getAlipayClient();
                System.out.println("tunnel:支付宝通道开启");
            } catch (Exception e) {
                System.out.println("tunnel:支付宝通道开启错误");
                e.printStackTrace();
            }
        }
    }

    /**
     * 支付宝获取授权authCode
     *
     * @param appid
     * @param url
     * @param state
     * @return
     */
    public String oauth2buildAuthorizationUrl(String appid, String url, String authBase, String state) {
        return "https://openauth.alipay.com/oauth2/publicAppAuthorize.htm?app_id=" + appid + "&scope=" + authBase + "&redirect_uri=" + url + "&state=" + state;
    }

    /**
     * 支付宝授权
     *
     * @param authCode
     * @return
     */
    public AlipaySystemOauthTokenResponse businessLogin(String authCode) throws AlipayApiException {
        AlipaySystemOauthTokenRequest alipaySystemOauthTokenRequest = new AlipaySystemOauthTokenRequest();
        alipaySystemOauthTokenRequest.setCode(authCode);
        alipaySystemOauthTokenRequest.setGrantType("authorization_code");
        try {
            AlipaySystemOauthTokenResponse oauthTokenResponse = alipayClient.execute(alipaySystemOauthTokenRequest);
            return oauthTokenResponse;
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 支付宝授权
     *
     * @param authCode
     * @return
     */
    public AlipaySystemOauthTokenResponse businessLogin(String authCode, String app_auth_token) throws AlipayApiException {
        AlipaySystemOauthTokenRequest alipaySystemOauthTokenRequest = new AlipaySystemOauthTokenRequest();
        alipaySystemOauthTokenRequest.setCode(authCode);
        alipaySystemOauthTokenRequest.setGrantType("authorization_code");
        alipaySystemOauthTokenRequest.putOtherTextParam("app_auth_token", app_auth_token);
        try {
            AlipaySystemOauthTokenResponse oauthTokenResponse = alipayClient.execute(alipaySystemOauthTokenRequest);
            return oauthTokenResponse;
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 创建订单
     *
     * @param buyerId
     * @param appAuthToken
     * @param sellerId
     * @param money
     * @param outTradeNo
     * @param notifyUrl
     * @return
     */
    public Object tradeCreate(String buyerId, String appAuthToken, String sellerId, String money, String outTradeNo, String notifyUrl) {
        System.out.println("进入创建订单");
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("out_trade_no", outTradeNo);
        params.put("seller_id", sellerId);//卖家支付宝ID
        params.put("total_amount", money);
        params.put("buyer_id", buyerId);
        params.put("subject", "mpay");
        //params.put("notify_url", "https://47.101.197.212/api/aliPay/ZFBCallback");

        Object obj = JSONObject.toJSON(params);
        AlipayTradeCreateRequest alipayRequest = new AlipayTradeCreateRequest();
        alipayRequest.setBizContent(obj.toString());
        alipayRequest.setNotifyUrl(notifyUrl);
        alipayRequest.putOtherTextParam("app_auth_token", appAuthToken);
        try {
            AlipayTradeCreateResponse alipayResponse = alipayClient.execute(alipayRequest);
            return alipayResponse;
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 支付订单
     *
     * @param out_trade_no
     * @param auth_code
     * @param total_amount
     * @param app_auth_token
     * @return
     */
    public Object tradePay(String out_trade_no, String auth_code,
                           BigDecimal total_amount, String app_auth_token) throws AlipayApiException {
        return tradePay(out_trade_no, auth_code, total_amount, app_auth_token, null);
    }

    /**
     * 支付订单
     *
     * @param out_trade_no
     * @param auth_code
     * @param total_amount
     * @param app_auth_token
     * @return
     */
    public Object tradePay(String out_trade_no, String auth_code,
                           BigDecimal total_amount, String app_auth_token, Map<String, Object> extend_params) throws AlipayApiException {
        AlipayTradePayRequest alipayRequest = new AlipayTradePayRequest();
        try {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("out_trade_no", out_trade_no);
            params.put("scene", "bar_code");
            params.put("auth_code", auth_code);
            params.put("total_amount", total_amount);
            params.put("subject", "mpay");
//            Map<String, Object> stage = new HashMap<String, Object>();
//            stage.put("hb_fq_num", "3");
//            stage.put("hb_fq_seller_percent", "0");
            if (extend_params!=null) {
                params.put("extend_params", extend_params);
            }
            Object obj = JSONObject.toJSON(params);
            System.out.println(obj);
            alipayRequest.setBizContent(obj.toString());
            alipayRequest.putOtherTextParam("app_auth_token", app_auth_token);

        } catch (Exception e) {
            System.out.println(e.getMessage());
            return null;
        }
        AlipayTradePayResponse alipayResponse = alipayClient.execute(alipayRequest);
        return alipayResponse;
    }

    public String pagePay(String out_trade_no,
                          BigDecimal total_amount, String app_auth_token) throws AlipayApiException {
        AlipayTradePagePayRequest request = new AlipayTradePagePayRequest();
//        // 订单完成后返回的页面和异步通知地址
//        request.setReturnUrl(alipay.getReturnUrl());
//        request.setNotifyUrl(alipay.getNotifyUrl());
        // 填充订单参数
        request.setBizContent("{" +
                "\"out_trade_no\":\""+out_trade_no+"\"," +
                "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"," +
                "\"total_amount\":"+total_amount+"," +
                "\"subject\":\"mpay\"," +
                "\"extend_params\":{" +
                "\"hb_fq_num\":\""+3+"\"," +
                "\"hb_fq_seller_percent\":\""+0+"\"" +
                "}"+
                "}");
        request.putOtherTextParam("app_auth_token", app_auth_token);
        return alipayClient.pageExecute(request, "GET").getBody();
    }

    /**
     * 冻结订单
     *
     * @param out_trade_no
     * @param auth_code
     * @param total_amount
     * @param app_auth_token
     * @return
     */
    public Object freeze(String out_trade_no, String auth_code,
                           BigDecimal total_amount, String app_auth_token) throws AlipayApiException {
        AlipayFundAuthOrderFreezeRequest alipayRequest = new AlipayFundAuthOrderFreezeRequest();
        try {
            Map<String, Object> params = new HashMap<String, Object>();
            params.put("out_request_no", out_trade_no);
            params.put("out_order_no", out_trade_no);
            params.put("auth_code_type", "bar_code");
            params.put("auth_code", auth_code);
            params.put("total_amount", total_amount);
            params.put("order_title", "预授权冻结");
            Object obj = JSONObject.toJSON(params);
            alipayRequest.setBizContent(obj.toString());
            alipayRequest.putOtherTextParam("app_auth_token", app_auth_token);
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
        AlipayFundAuthOrderFreezeResponse execute = alipayClient.execute(alipayRequest);
        return execute;
    }

    /**
     * 退款
     *
     * @param out_trade_no
     * @param refund_amount
     * @param app_auth_token
     * @return
     */
    public Object refund(String out_trade_no, BigDecimal refund_amount, String app_auth_token) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("out_trade_no", out_trade_no);
        params.put("refund_amount", refund_amount);
        Object obj = JSONObject.toJSON(params);
        AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();
        alipayRequest.setBizContent(obj.toString());
        alipayRequest.putOtherTextParam("app_auth_token", app_auth_token);
        try {
            AlipayTradeRefundResponse alipayResponse = alipayClient.execute(alipayRequest);
            return alipayResponse;
        } catch (AlipayApiException e) {
            if (e.getCause() instanceof java.security.spec.InvalidKeySpecException) {
                System.out.println("商户私钥格式不正确，请确认application.properties文件中是否配置正确");
            }
            return null;
        }
    }

    /**
     * 查询订单
     *
     * @param out_trade_no
     * @param app_auth_token
     * @return
     */
    public Object tradeQuery(String out_trade_no, String app_auth_token) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("out_trade_no", out_trade_no);
        Object obj = JSONObject.toJSON(params);
        AlipayTradeQueryRequest alipayRequest = new AlipayTradeQueryRequest();
        alipayRequest.setBizContent(obj.toString());
        alipayRequest.putOtherTextParam("app_auth_token", app_auth_token);
        try {
            AlipayTradeQueryResponse alipayResponse = alipayClient.execute(alipayRequest);
            return alipayResponse;
        } catch (AlipayApiException e) {
            if (e.getCause() instanceof java.security.spec.InvalidKeySpecException) {
                System.out.println("商户私钥格式不正确，请确认application.properties文件中是否配置正确");
            }
            return null;
        }
    }

    /**
     * 查询日账单下载地址
     *
     * @param app_auth_token
     * @return
     */
    public Object downloads(String app_auth_token, String date) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("bill_type", "trade");
        params.put("bill_date", date);
        Object obj = JSONObject.toJSON(params);
        AlipayDataDataserviceBillDownloadurlQueryRequest alipayDataDataserviceBillDownloadurlQueryRequest = new AlipayDataDataserviceBillDownloadurlQueryRequest();
        alipayDataDataserviceBillDownloadurlQueryRequest.setBizContent(obj.toString());
        alipayDataDataserviceBillDownloadurlQueryRequest.putOtherTextParam("app_auth_token", app_auth_token);
        try {
            AlipayDataDataserviceBillDownloadurlQueryResponse alipayDataDataserviceBillDownloadurlQueryResponse = alipayClient.execute(alipayDataDataserviceBillDownloadurlQueryRequest);
            return alipayDataDataserviceBillDownloadurlQueryResponse;
        } catch (AlipayApiException e) {
            System.out.println("调用SDK失败");
            return null;
        }
    }

    /**
     * 创建固定面额无资金优惠券
     *
     * @param app_auth_token
     * @param params
     * @return
     */
    public AlipayMarketingCashlessvoucherTemplateCreateResponse createCoupon(Map<String, Object> params, String app_auth_token) {
        AlipayMarketingCashlessvoucherTemplateCreateRequest request = new AlipayMarketingCashlessvoucherTemplateCreateRequest();
        params.put("voucher_type", "CASHLESS_FIX_VOUCHER");
        Map<String, Object> periodParams = new HashMap<String, Object>();
        periodParams.put("type", "ABSOLUTE");
        periodParams.put("start", params.get("start"));
        periodParams.put("end", params.get("end"));
        params.put("voucher_valid_period", periodParams);
        Map<String, Object> availableParam = new HashMap<String, Object>();
        availableParam.put("day_rule", params.get("day_rule"));
        availableParam.put("time_begin", params.get("time_begin"));
        availableParam.put("time_end", params.get("time_end"));
        ArrayList<Map<String, Object>> availableParams = new ArrayList<>();
        availableParams.add(availableParam);
        params.put("voucher_available_time", availableParams);
        params.put("voucher_description", params.get("voucher_description").toString().split("\n"));
        Map<String, Object> rule = new HashMap<String, Object>();
        rule.put("PID", params.get("PID"));
        params.put("rule_conf", rule);
        Object obj = JSONObject.toJSON(params);
        System.out.println(obj.toString());
        request.setBizContent(obj.toString());
        request.putOtherTextParam("app_auth_token", app_auth_token);
        try {
            AlipayMarketingCashlessvoucherTemplateCreateResponse response = alipayClient.execute(request);
            return response;
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 投放卡卷
     *
     * @param templateId
     * @param userId
     * @param outBizNo
     * @param app_auth_token
     * @return
     */
    public AlipayMarketingVoucherSendResponse sendCoupon(String templateId, String userId, String outBizNo, String app_auth_token) {
        AlipayMarketingVoucherSendRequest request = new AlipayMarketingVoucherSendRequest();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("template_id", templateId);
        params.put("user_id", userId);
        params.put("out_biz_no", outBizNo);
        Object obj = JSONObject.toJSON(params);
        request.setBizContent(obj.toString());
        request.putOtherTextParam("app_auth_token", app_auth_token);
        try {
            AlipayMarketingVoucherSendResponse response = alipayClient.execute(request);
            return response;
        } catch (AlipayApiException e) {
            System.out.println("调用支付宝投放接口失败");
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 上传图片
     *
     * @param file
     * @return
     */
    public String uploadImage(File file, String app_auth_token) {
        AlipayOfflineMaterialImageUploadRequest request = new AlipayOfflineMaterialImageUploadRequest();
        int lastIndexOf = file.getName().lastIndexOf(".");
        //获取文件的后缀名 .jpg
        String suffix = file.getName().substring(lastIndexOf + 1);
        request.setImageType(suffix);
//        System.out.println(suffix);
        request.setImageName(file.getName());
        FileItem ImageContent = new FileItem(file);
//        System.out.println(file);
        request.setImageContent(ImageContent);
        request.putOtherTextParam("app_auth_token", app_auth_token);
//        request.setImagePid("2088021822217233");
        try {
            AlipayOfflineMaterialImageUploadResponse response = alipayClient.execute(request);
            if (response.isSuccess()) {
                return response.getImageId();
            } else {
                throw new RuntimeException(response.getMsg());
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new RuntimeException("调用支付宝上传图片接口失败");
        }
    }

    /**
     * 创建支付宝会员卡模板
     *
     * @param params
     * @param app_auth_token
     * @return
     */
    public AlipayMarketingCardTemplateCreateResponse createMemberCard(Map<String, Object> params, String app_auth_token) {
        AlipayMarketingCardTemplateCreateRequest request = new AlipayMarketingCardTemplateCreateRequest();
        Object obj = JSONObject.toJSON(params);
        System.out.println(obj.toString());
        request.setBizContent(obj.toString());
        request.putOtherTextParam("app_auth_token", app_auth_token);
        try {
            AlipayMarketingCardTemplateCreateResponse response = alipayClient.execute(request);
            return response;
        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new RuntimeException("调用支付宝创建会员卡接口失败");
        }
    }

    /**
     * 修改支付宝会员卡模板
     *
     * @param params
     * @param app_auth_token
     * @return
     */
    public AlipayMarketingCardTemplateModifyResponse updateMemberCard(Map<String, Object> params, String app_auth_token) {
        AlipayMarketingCardTemplateModifyRequest request = new AlipayMarketingCardTemplateModifyRequest();
        Object obj = JSONObject.toJSON(params);
        request.setBizContent(obj.toString());
        request.putOtherTextParam("app_auth_token", app_auth_token);
        try {
            AlipayMarketingCardTemplateModifyResponse response = alipayClient.execute(request);
            return response;
        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new RuntimeException("调用支付宝修改会员卡接口失败");
        }
    }

    /**
     * 会员卡开卡表单模板配置
     *
     * @param template_id
     * @param fields
     * @param app_auth_token
     * @return
     */
    public AlipayMarketingCardFormtemplateSetResponse setMemberCardForm(String template_id, String[] fields, String app_auth_token) {
        AlipayMarketingCardFormtemplateSetRequest request = new AlipayMarketingCardFormtemplateSetRequest();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("template_id", template_id);
        Map<String, Object> fieldsIn = new HashMap<>();
        Map<String, Object> requiredMap = new HashMap<>();
        requiredMap.put("common_fields", fields);
        fieldsIn.put("optional", requiredMap);
        params.put("fields", fieldsIn);
        Object obj = JSONObject.toJSON(params);
        request.setBizContent(obj.toString());
        request.putOtherTextParam("app_auth_token", app_auth_token);
        try {
            AlipayMarketingCardFormtemplateSetResponse response = alipayClient.execute(request);
            return response;
        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new RuntimeException("调用配置表单失败");
        }
    }

    /**
     * 获取投放二维码
     *
     * @param template_id
     * @param callback
     * @param app_auth_token
     * @return
     */
    public AlipayMarketingCardActivateurlApplyResponse applyMemberCard(String template_id, String out_string, String callback, String app_auth_token) {
        AlipayMarketingCardActivateurlApplyRequest request = new AlipayMarketingCardActivateurlApplyRequest();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("template_id", template_id);
        params.put("callback", callback);
        if (out_string != null) {
            params.put("out_string", out_string);
        }
        Object obj = JSONObject.toJSON(params);
        request.setBizContent(obj.toString());
        request.putOtherTextParam("app_auth_token", app_auth_token);
        try {
            AlipayMarketingCardActivateurlApplyResponse response = alipayClient.execute(request);
            return response;
        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new RuntimeException("调用支付宝会员卡二维码接口失败");
        }
    }

    /**
     * 获取用户提交信息
     * @param template_id
     * @param request_id
     * @param app_auth_token
     * @return
     */
    public AlipayMarketingCardActivateformQueryResponse memberActivateformQuery(String template_id, String request_id, String accessToken, String app_auth_token) {
        AlipayMarketingCardActivateformQueryRequest request = new AlipayMarketingCardActivateformQueryRequest();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("biz_type", "MEMBER_CARD");
        params.put("template_id", template_id);
        params.put("request_id", request_id);
        Object obj = JSONObject.toJSON(params);
        request.setBizContent(obj.toString());
        request.putOtherTextParam("app_auth_token", app_auth_token);
        try {
            AlipayMarketingCardActivateformQueryResponse response = alipayClient.execute(request, accessToken);
//            //解析出返回的json串
            JSONArray fields = new JSONArray(response.getInfos());
            Map<String, String> map = new HashMap<String, String>();
            for(int i=0; i<fields.size(); i++){
                cn.hutool.json.JSONObject row = fields.getJSONObject(i);
                if (row.containsKey("OPEN_FORM_FIELD_MOBILE")) {
                    map.put("phone", row.getStr("OPEN_FORM_FIELD_MOBILE"));
                }
                if (row.containsKey("OPEN_FORM_FIELD_NAME")) {
                    map.put("username", row.getStr("OPEN_FORM_FIELD_NAME"));
                }
            }
            response.setParams(map); // 为了把数据传出去借用Params
            return response;
        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new RuntimeException("调用支付宝会员卡查询表单失败");
        }
    }

    /**
     * 投放会员卡
     * @param params
     * @param accessToken
     * @param app_auth_token
     * @return
     */
    public AlipayMarketingCardOpenResponse openMemberCard(Map<String, Object> params, String accessToken, String app_auth_token) {
        AlipayMarketingCardOpenRequest request = new AlipayMarketingCardOpenRequest();
        Object obj = JSONObject.toJSON(params);
        request.setBizContent(obj.toString());
        request.putOtherTextParam("app_auth_token", app_auth_token);
        try {
            AlipayMarketingCardOpenResponse response = alipayClient.execute(request, accessToken);
            return response;
        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new RuntimeException("调用支付宝会员卡开卡失败");
        }

    }

    /**
     * 修改积分
     * @param cardNo
     * @param bonus
     * @param app_auth_token
     * @return
     */
    public AlipayMarketingCardUpdateResponse changeBonus(String cardNo, Integer bonus, String app_auth_token) {
        AlipayMarketingCardUpdateRequest request = new AlipayMarketingCardUpdateRequest();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("target_card_no", cardNo);
        params.put("target_card_no_type", "BIZ_CARD");
        params.put("occur_time", DateUtils.getNow());
        Map<String, Object> cardInfo = new HashMap<String, Object>();
        cardInfo.put("open_date", DateUtils.getNow());
        cardInfo.put("valid_date", DateUtils.getAfterYearNow(20));
        cardInfo.put("point", bonus.toString());
        params.put("card_info", cardInfo);
        Object obj = JSONObject.toJSON(params);
        request.setBizContent(obj.toString());
        request.putOtherTextParam("app_auth_token", app_auth_token);
        try {
            AlipayMarketingCardUpdateResponse response = alipayClient.execute(request);
            return response;
        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new RuntimeException("更新用户会员卡成功");
        }
    }

    /**
     * 修改余额
     * @param cardNo
     * @param balance
     * @param app_auth_token
     * @return
     */
    public AlipayMarketingCardUpdateResponse changeBalance(String cardNo, BigDecimal balance, String app_auth_token) {
        AlipayMarketingCardUpdateRequest request = new AlipayMarketingCardUpdateRequest();
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("target_card_no", cardNo);
        params.put("target_card_no_type", "BIZ_CARD");
        params.put("occur_time", DateUtils.getNow());
        Map<String, Object> cardInfo = new HashMap<String, Object>();
        cardInfo.put("open_date", DateUtils.getNow());
        cardInfo.put("valid_date", DateUtils.getAfterYearNow(20));
        cardInfo.put("balance", balance.toString());
        params.put("card_info", cardInfo);
        Object obj = JSONObject.toJSON(params);
        request.setBizContent(obj.toString());
        request.putOtherTextParam("app_auth_token", app_auth_token);
        try {
            AlipayMarketingCardUpdateResponse response = alipayClient.execute(request);
            return response;
        } catch (AlipayApiException e) {
            e.printStackTrace();
            throw new RuntimeException("更新用户会员卡成功");
        }
    }
}
